/*
 * @Description:
 * @Version: 2.0
 * @Autor: zss
 * @Date: 2024-11-18 10:22:27
 * @LastEditors: zss
 * @LastEditTime: 2025-05-26 18:12:37
 */
import { Tsrv, ifs, ts } from '@/services';
import { N_cPLDetails } from '../types';
// import { T_shceduleHandle } from './scheduleHandle';
import { T_pldBase } from './base';

class T_productLog extends T_pldBase {
  private businessNums: N_cPLDetails.businessNumInfo[] = [];

  // 槽编号与槽名称
  private slotInfo = {
    '1': '化学除油1槽',
    '2': '碱腐蚀2槽',
    '3': '热水洗3槽',
    '4': '冷水洗4槽',
    '5': '冷水洗5槽',
    '6': '出光6槽',
    '7': '冷水洗7槽',
    '8': '冷水洗8槽',
    '9': '纯水洗9槽',
    '10': '交换位10槽',
    '11': '硫酸阳极化11槽',
    '12': '硫酸阳极化12槽',
    '13': '冷水洗13槽',
    '14': '冷水洗14槽',
    '15': '铬酸阳极化15槽',
    '16': '回收水洗16槽',
    '17': '冷水洗17槽',
    '18': '冷水洗18槽',
    '19': '纯水洗19槽',
    '20': '铬酸盐封闭20槽',
    '21': '回收水洗21槽',
    '22': '冷水洗22槽',
    '23': '冷水洗23槽',
    '24': '热水封闭24',
    '25': '热水封闭25槽',
    '26': '吹干26槽',
    '27': '烘干27槽',
    '28': '缓存位28',
    '29': '缓存位29',
    '30': '缓存位30',
    '31': '缓存位31',
    '32': '上下料位32'
  };

  // 当前加工挂组在几号槽,最大加工数为4
  private currentSlots = [];

  // 行车编号
  private carNums = [132, 133];

  // 业务编号与行车实际工位
  private actualWorkCode = [130, 131];

  // 行车挂组id
  private carGroupIds = [134, 135];

  // 车上挂组id代号
  private carHangGroupNums = ['my324', 'my325'];

  // 当前工位
  private currentStation;

  // 当前槽id
  private currentSlotId = null;

  // 当前挂组id
  private currentGroupInfo = {
    id: undefined,
    hang_group_num: undefined,
    physical_num: undefined,
    is_automated_produc: undefined
  };

  // 当前是几号行车
  private currentCar;

  // 当前工位加工时间
  private currentProcessTime = null;

  // 映射
  private valueMap = {
    '液位-1': '高',
    '液位-0': '低',
    '搅拌-1': '开',
    '搅拌-0': '关',
    '喷淋-1': '开',
    '喷淋-0': '关',
    '过滤机-1': '开',
    '过滤机-0': '关',
    '超声波运行-1': '开',
    '超声波运行-0': '关'
  };

  // 主槽加工时间编号集
  private mainSlotProcessTimeNums = [400, 420, 480];

  // 主槽加工时间
  private mainSlotProcessTime = null;

  // 单元订单生产执行时间
  private unitOrderExecuteTime = null;

  // {挂组id：{nowTime：当前时间，carStayTime：行车停留时间}}

  // 挂组停留时间计算不准确，暂时不用（包括行车移动时间和行车下降时间，挂组停留时间应已工艺槽工作时间为准）
  // 挂组号：行车停留时间
  // private hangGroupStayTime = new Map<
  //   number,
  //   { nowTime: number; carStayTime: number }
  // >();

  // 获取业务编号表数据
  public getappNums() {
    this.doLoadData(this.tableName.businessNumTbale).then(
      ([b, res, rows, err]) => {
        if (!b) {
          this.self.$msg(err);
        } else {
          this.businessNums = rows.map(item => ({
            businessNum: item.business_num,
            fName: item['m2o|para_id|produc_process_para|title'],
            conversionRate: item.conversion_rate || 1,
            processTank: item['m2o|process_tank_id|process_tank|f_name'],
            processTankId: item.process_tank_id,
            paraId: item.para_id
          }));
        }
      }
    );
  }

  // 预处理SCADA数据
  private preprocessScadaData(
    items: N_cPLDetails.T_msgScadaModbusSubscription[]
  ) {
    this.currentSlots = [];

    items.forEach(item => {
      this.confirmCurrentInfo(item);

      const businessItem = this.businessNums.find(
        item1 =>
          item1.businessNum === item.appNum &&
          !Tsrv.noValue(item1.processTankId)
      );

      if (!businessItem) return;

      let value = item.value;
      if (businessItem.conversionRate !== 1) {
        value = item.value / businessItem.conversionRate;
      } else {
        const key = `${businessItem.fName}-${item.value}`;
        value = this.valueMap[key] ?? item.value;
      }

      this.currentSlots.push([
        { field: 'id', value: Tsrv.getSnowIDFmtStr() } as ifs.I_fv,
        { field: 'para_id', value: businessItem.paraId } as ifs.I_fv,
        { field: 'parameter_value', value } as ifs.I_fv,
        {
          field: 'process_tank_id',
          value: businessItem.processTankId
        } as ifs.I_fv
      ]);

      this.currentSlotId = businessItem.processTankId;

      if (businessItem.fName === '工作时间S') {
        this.currentProcessTime = item.value;
        if (this.mainSlotProcessTimeNums.includes(businessItem.businessNum)) {
          this.mainSlotProcessTime = item.value / 3600;
          this.completeCurrentInfo();
        }
      }
    });
  }

  // 写入行车日志
  private async writeCarLog() {
    const title = `${this.currentCar}号行车在${
      this.slotInfo[this.currentStation]
    }工位完成${this.currentGroupInfo.hang_group_num}号挂组吊装作业，实际用时${
      this.currentProcessTime
    }秒`;

    const hGLogRow = [
      [
        { field: 'id', value: Tsrv.getSnowIDFmtStr() },
        { field: 'master_bill_id', value: this.currentGroupInfo.id },
        { field: 'title', value: title }
      ] as ifs.I_fv[]
    ];

    const dLogRow = [
      [
        { field: 'id', value: Tsrv.getSnowIDFmtStr() },
        { field: 'driving_num', value: this.currentCar },
        { field: 'title', value: title },
        { field: 'master_bill_id', value: this.currentGroupInfo.id }
      ] as ifs.I_fv[]
    ];

    try {
      await this.addTableData(this.tableName.hGLog, hGLogRow);
      await this.addTableData(this.tableName.dLog, dLogRow);
      return true;
    } catch (error) {
      this.self.$msg(`写入行车日志失败: ${error.message}`);
      return false;
    }
  }

  // 写入工艺槽日志
  private async writeProcessTankLog() {
    this.currentSlots.forEach(row => {
      row.push({
        field: 'master_bill_id',
        value: this.currentGroupInfo.id
      } as ifs.I_fv);
    });

    if (this.currentGroupInfo.is_automated_produc && !this.isAutoProduce) {
      const Tfilter = new ts.T_filter();
      const filter = Tfilter.parseAND([
        Tfilter.parseEQ('master_bill_id', this.currentGroupInfo.id),
        Tfilter.parseEQ('process_tank_id', this.currentSlotId),
        Tfilter.parseIN(
          'para_id',
          this.currentSlots.map(
            el => el.find(item => item.field === 'para_id')?.value
          )
        )
      ]);

      const [b, res, rows] = await this.doLoadData(
        this.tableName.pTLog,
        filter
      );
      if (b && rows.length > 0) {
        rows.forEach(rowData => {
          this.currentSlots[0].forEach(item => {
            if (
              item.field === 'para_id' &&
              item.value === rowData.produc_para_id
            ) {
              item.value = rowData.parameter_value;
            }
          });
        });
      }
    }

    try {
      await this.addTableData(this.tableName.pTLog, this.currentSlots);
      return true;
    } catch (error) {
      this.self.$msg(`写入工艺槽日志失败: ${error.message}`);
      return false;
    }
  }

  // 接收scada数据
  public async receiveScadaData(data: ifs.I_receWsMsgParams) {
    const d = data.m.d as N_cPLDetails.T_msgScadaModbusSubscription[];
    if (Tsrv.noValue(d) || !Tsrv.utils.isArray(d)) return;

    this.preprocessScadaData(d);

    if (
      Tsrv.noValue(this.currentCar) ||
      Tsrv.noValue(this.currentStation) ||
      Tsrv.noValue(this.currentGroupInfo)
    ) {
      return;
    }

    try {
      const carLogSuccess = await this.writeCarLog();
      if (!carLogSuccess) return;

      const processLogSuccess = await this.writeProcessTankLog();
      if (!processLogSuccess) return;

      // 重置状态
      this.resetCurrentState();
    } catch (error) {
      this.self.$msg(`处理SCADA数据失败: ${error.message}`);
    }
  }

  // 重置当前状态
  private resetCurrentState() {
    this.currentSlots = [];
    this.currentCar = null;
    this.currentStation = null;
    this.currentSlotId = null;
    this.currentGroupInfo = null;
    this.currentProcessTime = null;
  }

  // 确认当前信息
  private confirmCurrentInfo(item: N_cPLDetails.T_msgScadaModbusSubscription) {
    // 辅助函数，用于检查是否存在匹配的appNum 且value 不为0
    const matches = (arr: number[], appNum: number, value: number): boolean => {
      return arr.some(el => el === appNum && value !== 0);
    };

    // 确认当前行车
    if (matches(this.carNums, item.appNum, item.value)) {
      this.currentCar =
        item.appNum === 132 ? 1 : item.appNum === 133 ? 2 : null;
    }

    // 如果需要单独读取行车挂组id数据，采用以下代码
    // this.readPlcData(this.carHangGroupNums).then(data => {
    //   if (typeof data === 'boolean') return;
    //   Object.keys(data).forEach(key => {
    //     if (data[key].v !== '0') {
    //       this.currentCar = data[key].v;
    //     }
    //   });
    // });

    // 确认当前行车挂组id
    if (matches(this.carGroupIds, item.appNum, item.value)) {
      this.currentGroupInfo = this.topBaseGrid.cloudData.find(
        el => el.physical_num === item.value
      );
    }

    // 确认当前行车实际工位
    if (matches(this.actualWorkCode, item.appNum, item.value)) {
      this.currentStation = item.value;
    }
  }

  // 完善当前挂组主槽加工时间与单元订单执行时间
  private completeCurrentInfo() {
    // 单元订单执行时间为公式计算得出，需获取单元订单执行时间换算公式
    this.getFormula();
  }

  // 获取计算公式
  private getFormula() {
    // eslint-disable-next-line camelcase
    const filter = { production_line: this.self.formData.id };
    this.doLoadData(this.tableName.timeConversionConfig, filter).then(
      ([b, res, rows, err]) => {
        if (!b) {
          this.self.$msg(err);
        } else {
          if (rows.length > 0) {
            // 判断是否特殊处理产线
            if (rows[0]['is_special_case'] === 1) {
              // 使用区间换算公式，即time_ranges字段，json如下
              // [{"max": 2, "min": 0, "factor": 2}, {"max": 8, "min": 2, "factor": 1.5}, {"min": 8, "factor": 1.2}]
              const timeRanges = JSON.parse(rows[0]['time_ranges']);
              // 遍历区间换算公式，找到当前时间所在区间，并计算单元订单执行时间，单元订单执行时间 = 当前主槽加工时间 * 区间换算公式系数
              for (const range of timeRanges) {
                if (
                  this.mainSlotProcessTime >= range.min &&
                  this.mainSlotProcessTime <= range.max
                ) {
                  this.unitOrderExecuteTime =
                    this.mainSlotProcessTime * range.factor;
                  break;
                } else if (this.mainSlotProcessTime > range.max) {
                  this.unitOrderExecuteTime =
                    this.mainSlotProcessTime * range.factor;
                  break;
                }
              }
            } else {
              // 使用基础换算系数，即base_conversion_factor字段
              this.unitOrderExecuteTime =
                this.mainSlotProcessTime * rows[0]['base_conversion_factor'];
            }

            // 更新当前挂组主槽加工时间与单元订单执行时间
            this.updateCurrentGroupInfo();
          }
        }
      }
    );
  }

  // 更新当前挂组主槽加工时间与单元订单执行时间
  private updateCurrentGroupInfo() {
    const updateData = [
      [
        {
          field: 'id',
          value: this.currentGroupInfo.id
        } as ifs.I_fv,
        {
          field: 'main_slot_process_time',
          value: this.mainSlotProcessTime
        } as ifs.I_fv,
        {
          field: 'unit_order_execution_time',
          value: Math.round(this.unitOrderExecuteTime * 100) / 100
        } as ifs.I_fv
      ]
    ];

    this.modifyData(this.tableName.pLDetails, this.filterName.ID, updateData);
  }
}
interface I_productLog extends T_productLog {}
export { I_productLog, T_productLog };
